﻿using System.Linq;
using NUnit.Framework;

namespace TeF.Runner.Tests
{
    [TestFixture]
    public class ManagerTests
    {
        [Test]
        public void Test_LoadTestAssembly_Usual()
        {
            // Arrange
            var manager = ManagerFactory.Create();

            // Act
            var assembly = manager.LoadTestAssembly("TeF.Runner.Tests.LoadTestAssembly.UsualTestAssembly.dll");

            // Assert
            Assert.AreEqual(TestState.Loaded, assembly.State);
            Assert.AreEqual("TeF.Runner.Tests.LoadTestAssembly.UsualTestAssembly", assembly.Name);

            var namespaces = assembly.Namespaces.ToArray();
            Assert.AreEqual(2, namespaces.Length);

            // Namespace #1
            var namespace1 = namespaces[0];
            Assert.AreEqual(TestState.Loaded, namespace1.State);
            Assert.AreEqual("TeF.Runner.Tests.LoadTestAssembly.UsualTestAssembly", namespace1.Name);

            var containers1 = namespace1.Containers.ToArray();
            Assert.AreEqual(1, containers1.Length);

            var container11 = containers1[0];
            Assert.AreEqual(TestState.Loaded, container11.State);
            Assert.AreEqual("UsualTestContainer2", container11.Name);

            var tests11 = container11.Tests.ToArray();
            Assert.AreEqual(3, tests11.Length);

            var test111 = tests11[0];
            Assert.AreEqual(TestState.Skipped, test111.State);
            Assert.AreEqual("IgnoredTest", test111.Name);

            var test112 = tests11[1];
            Assert.AreEqual(TestState.Loaded, test112.State);
            Assert.AreEqual("UsualTest_1", test112.Name);

            var test113 = tests11[2];
            Assert.AreEqual(TestState.Loaded, test113.State);
            Assert.AreEqual("UsualTest_2", test113.Name);

            // Namespace #2
            var namespace2 = namespaces[1];
            Assert.AreEqual(TestState.Loaded, namespace2.State);
            Assert.AreEqual("TeF.Runner.Tests.LoadTestAssembly.UsualTestAssembly.TestNamespace", namespace2.Name);

            var containers2 = namespace2.Containers.ToArray();
            Assert.AreEqual(2, containers2.Length);

            var container21 = containers2[0];
            Assert.AreEqual(TestState.Skipped, container21.State);
            Assert.AreEqual("IgnoredTestContainer", container21.Name);

            var tests21 = container21.Tests.ToArray();
            Assert.AreEqual(2, tests21.Length);

            var test211 = tests21[0];
            Assert.AreEqual(TestState.Skipped, test211.State);
            Assert.AreEqual("IgnoredTest", test211.Name);

            var test212 = tests21[1];
            Assert.AreEqual(TestState.Skipped, test212.State);
            Assert.AreEqual("UsualTest", test212.Name);

            var container22 = containers2[1];
            Assert.AreEqual(TestState.Loaded, container22.State);
            Assert.AreEqual("UsualTestContainer1", container22.Name);

            var tests22 = container22.Tests.ToArray();
            Assert.AreEqual(2, tests22.Length);

            var test221 = tests22[0];
            Assert.AreEqual(TestState.Skipped, test221.State);
            Assert.AreEqual("IgnoredTest", test221.Name);

            var test222 = tests22[1];
            Assert.AreEqual(TestState.Loaded, test222.State);
            Assert.AreEqual("UsualTest", test222.Name);
        }

        [Test]
        public void Test_LoadTestAssembly_IgnoredAssembly()
        {
            // Arrange
            var manager = ManagerFactory.Create();

            // Act
            var assembly = manager.LoadTestAssembly("TeF.Runner.Tests.LoadTestAssembly.IgnoredTestAssembly.dll");

            // Assert
            Assert.AreEqual(TestState.Skipped, assembly.State);
            Assert.AreEqual("TeF.Runner.Tests.LoadTestAssembly.IgnoredTestAssembly", assembly.Name);

            var namespaces = assembly.Namespaces.ToArray();
            Assert.AreEqual(2, namespaces.Length);

            // Namespace #1
            var namespace1 = namespaces[0];
            Assert.AreEqual(TestState.Skipped, namespace1.State);
            Assert.AreEqual("TeF.Runner.Tests.LoadTestAssembly.IgnoredTestAssembly", namespace1.Name);

            var containers1 = namespace1.Containers.ToArray();
            Assert.AreEqual(1, containers1.Length);

            var container11 = containers1[0];
            Assert.AreEqual(TestState.Skipped, container11.State);
            Assert.AreEqual("UsualTestContainer2", container11.Name);

            var tests11 = container11.Tests.ToArray();
            Assert.AreEqual(3, tests11.Length);

            var test111 = tests11[0];
            Assert.AreEqual(TestState.Skipped, test111.State);
            Assert.AreEqual("IgnoredTest", test111.Name);

            var test112 = tests11[1];
            Assert.AreEqual(TestState.Skipped, test112.State);
            Assert.AreEqual("UsualTest_1", test112.Name);

            var test113 = tests11[2];
            Assert.AreEqual(TestState.Skipped, test113.State);
            Assert.AreEqual("UsualTest_2", test113.Name);

            // Namespace #2
            var namespace2 = namespaces[1];
            Assert.AreEqual(TestState.Skipped, namespace2.State);
            Assert.AreEqual("TeF.Runner.Tests.LoadTestAssembly.IgnoredTestAssembly.TestNamespace", namespace2.Name);

            var containers2 = namespace2.Containers.ToArray();
            Assert.AreEqual(2, containers2.Length);

            var container21 = containers2[0];
            Assert.AreEqual(TestState.Skipped, container21.State);
            Assert.AreEqual("IgnoredTestContainer", container21.Name);

            var tests21 = container21.Tests.ToArray();
            Assert.AreEqual(2, tests21.Length);

            var test211 = tests21[0];
            Assert.AreEqual(TestState.Skipped, test211.State);
            Assert.AreEqual("IgnoredTest", test211.Name);

            var test212 = tests21[1];
            Assert.AreEqual(TestState.Skipped, test212.State);
            Assert.AreEqual("UsualTest", test212.Name);

            var container22 = containers2[1];
            Assert.AreEqual(TestState.Skipped, container22.State);
            Assert.AreEqual("UsualTestContainer1", container22.Name);

            var tests22 = container22.Tests.ToArray();
            Assert.AreEqual(2, tests22.Length);

            var test221 = tests22[0];
            Assert.AreEqual(TestState.Skipped, test221.State);
            Assert.AreEqual("IgnoredTest", test221.Name);

            var test222 = tests22[1];
            Assert.AreEqual(TestState.Skipped, test222.State);
            Assert.AreEqual("UsualTest", test222.Name);
        }

        [Test]
        public void Test_Run_Usual()
        {
            // Arrange
            var manager = ManagerFactory.Create();
            var assembly = manager.LoadTestAssembly("TeF.Runner.Tests.Run.dll");
            manager.RunCompleted +=
                (sender, args) =>
                {
                    // Assert
                    Assert.AreEqual(TestState.Failed, assembly.State);

                    var ns = assembly.Namespaces.Single();
                    Assert.AreEqual(TestState.Failed, ns.State);

                    var containers = ns.Containers.ToArray();

                    var container1 = containers[0];
                    Assert.AreEqual(TestState.Failed, container1.State);
                    var tests1 = container1.Tests.ToArray();
                    var test11 = tests1[0];
                    Assert.AreEqual(TestState.Failed, test11.State);
                    var test12 = tests1[1];
                    Assert.AreEqual(TestState.Failed, test12.State);

                    var container2 = containers[1];
                    Assert.AreEqual(TestState.Failed, container2.State);
                    var tests2 = container2.Tests.ToArray();
                    var test21 = tests2[0];
                    Assert.AreEqual(TestState.Failed, test21.State);
                    var test22 = tests2[1];
                    Assert.AreEqual(TestState.Passed, test22.State);
                    var test23 = tests2[1];
                    Assert.AreEqual(TestState.Skipped, test23.State);

                    var container3 = containers[2];
                    Assert.AreEqual(TestState.Failed, container3.State);
                    var tests3 = container3.Tests.ToArray();
                    var test31 = tests3[0];
                    Assert.AreEqual(TestState.Failed, test31.State);
                    var test32 = tests3[1];
                    Assert.AreEqual(TestState.Passed, test32.State);

                    var container4 = containers[3];
                    Assert.AreEqual(TestState.Passed, container4.State);
                    var tests4 = container4.Tests.ToArray();
                    var test41 = tests4[0];
                    Assert.AreEqual(TestState.Passed, test41.State);
                    var test42 = tests4[1];
                    Assert.AreEqual(TestState.Passed, test42.State);
                };

            // Act
            manager.RunAsync(new[] { assembly });
        }
    }
}
